<?php
namespace core\models;
/**
 * 文件上传封装
 * @author lwkai 2016-7-19
 */
class Widget_UpLoad {

    /**
     * 文件域的名称
     * @var string
     */
    private $file = '';

    /**
     * 上传的临时图片文件位置
     * @var string
     */
    private $tmp_filename = '';

    /**
     * 上传目录
     * @var string
     */
    private $destination = '';

    /**
     * 允许上传的文件扩展名
     * @var array
     */
    private $extensions = array();

    /**
     * 出现的错误信息
     * @var string
     */
    private $errmsg = '';

    /**
     * 保存文件名
     * @var string
     */
    private $filename = '';

    /**
     * 文件权限
     * @var string
     */
    private $permissions = '777';

    /**
     * 是否按日期建立目录
     * @var bool
     */
    private $datebydirectory = false;

    /**
     * @param string $file 文件域的名称
     * @param string $destination 上传位置【不含文件名的目录路径】,如果不存在，则会创建目录
     * @param string|array $extensions 允许哪些扩展名的文件上传
     * @param string $permissions 文件权限
     */
    public function __construct($file = '', $destination = '', $extensions = '', $permissions = '777'){
        $this->setFile($file);
        $this->setDestination($destination);
        $this->setPermissions($permissions);
        $this->setExtensions($extensions);
    }

    /**
     * 设置文件域的名称
     * @param $file
     * @author by lwkai
     * @date   2016-7-19
     */
    public function setFile($file) {
        $this->file = $file;
    }

    /**
     * 设置上传的目录
     * @param string $destination
     * @author by lwkai
     * @date   2016-7-19
     */
    public function setDestination($destination) {
        $this->destination = $destination;
        if ($this->destination && substr($this->destination, -1) != DIRECTORY_SEPARATOR) $this->destination .= DIRECTORY_SEPARATOR;
    }

    /**
     * 设置文件权限
     * @param $permissions
     * @author by lwkai
     * @date   2016-7-19
     */
    public function setPermissions($permissions) {
        $this->permissions = octdec($permissions);
    }

    /**
     * 设置允许的扩展名
     * @param array|string $extensions 允许的扩展名
     * @author by lwkai
     * @date   2016-7-19
     */
    public function setExtensions($extensions) {
        if ($extensions) {
            if (is_array($extensions)) {
                $this->extensions = $extensions;
            } else {
                $this->extensions = array($extensions);
            }
        } else {
            $this->extensions = array();
        }
    }

    /**
     * 文件是否在指定目录下，按日期年月来分开存放。如果调用此方法，则表示在你指定的目录下，上传的文件自动按当前年和月来分开存放。
     * @author lwkai
     * @date   2016-7-19
     */
    public function dateByDirectory(){
        $this->datebydirectory = true;
    }

    /**
     * 设置保存时的文件名称
     * @param string $filename 文件名，不需要路径
     * @author by lwkai
     * @date   2016-7-19
     */
    private function setFilename($filename) {
        $this->filename = $filename;
    }

    /**
     * 保存图片,失败返回FALSE，成功则返回图片绝对路径
     * @param string $filename 保存的文件名称，如果为空，则自动随机生成一个文件名。
     * @return bool|string
     * @author by lwkai
     * @date   2016-7-19
     */
    public function save($filename = '') {
        $this->parse($filename);
        if($this->errmsg) {
            return false;
        }
        if (move_uploaded_file($this->tmp_filename, $this->destination . $this->filename)) {
            chmod($this->destination . $this->filename, $this->permissions);
            return preg_replace('/' . preg_quote(DIRECTORY_SEPARATOR,'/') . '/','/',$this->destination) . $this->filename;
        }
        return false;
    }

    /**
     * 取得出错信息
     * @return string
     * @author lwkai
     * @date   2016-7-19
     */
    public function getErrInfo(){
        return $this->errmsg;
    }


    /**
     * 分析是否有错误发生
     * @param string $filename 要保存的文件名。
     * @author by lwkai modify
     * @date   2016-7-19
     */
    private function parse($filename = '') {
        $file = array();
        if (isset($_FILES[$this->file])) {
            $file = array(
                'name'     => $_FILES[$this->file]['name'],
                'type'     => $_FILES[$this->file]['type'],
                'size'     => $_FILES[$this->file]['size'],
                'tmp_name' => $_FILES[$this->file]['tmp_name'],
                'error'    => $_FILES[$this->file]['error']
            );
        } elseif (isset($HTTP_POST_FILES[$this->file])) {
            $file = array(
                'name'     => $HTTP_POST_FILES[$this->file]['name'],
                'type'     => $HTTP_POST_FILES[$this->file]['type'],
                'size'     => $HTTP_POST_FILES[$this->file]['size'],
                'tmp_name' => $HTTP_POST_FILES[$this->file]['tmp_name'],
                'error'    => $HTTP_POST_FILES[$this->file]['error']
            );
        }

        if ($file['error'] > 0) {
            $this->errmsg = $this->_getErrMsg($file['error']);
            return;
        }

        if($this->datebydirectory) {
            $this->destination .= date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR;
        }
        if(!\Z::DirFile()->createDir($this->destination,$this->permissions)) {
            $this->errmsg = 'Failed to create directory!';
            return;
        }
        if ($file['tmp_name'] && $file['tmp_name'] != 'none' && is_uploaded_file($file['tmp_name'])) {
            if (sizeof($this->extensions) > 0) {
                if (!in_array(strtolower(substr($file['name'], strrpos($file['name'], '.') + 1)), $this->extensions)) {
                    $this->errmsg = 'Error file type not allowed!';
                    return;
                }
            }
            if (!$filename) {
                //$file['name']  用这个，如果是中文名，就会有问题。所以改成用日期加随机。
                $this->setFilename(date('YmdHis') . mt_rand(1111,9999) . '.' . (preg_replace('/^.+\./', '', $file['name'])));
            } else {
                if (!preg_match('/\./', $filename)) {
                    $filename = $filename . '.' . (preg_replace('/^.+\./', '', $file['name']));
                }
                if(file_exists($this->destination . $filename)) {
                    $this->errmsg = 'File already exists!';
                    return;
                }
                $this->setFilename($filename);
            }
            if(!\Z::DirFile()->isWritable($this->destination)) {
                $this->errmsg = 'Directory is not writable!';
                return;
            }
            $this->tmp_filename = $file['tmp_name'];
        } else {
            $this->errmsg = 'No File Uploaded!';
        }
    }

    /**
     * 把上传文件错误转化为对应说明
     * @param int $err_no 文件上传出错时的代码 ($_FILES['upload']['error'])
     * @return string
     * @author lwkai
     * @date   2016-7-19
     */
    private function _getErrMsg($err_no) {
        $rtn = '';
        switch($err_no) {
            case 1:
                $rtn = 'Exceeds upload_max_filesize settings!';
                break;
            case 2:
                $rtn = 'Exceeds HTML MAX_FILE_SIZE settings!';
                break;
            case 3:
                $rtn = 'File was only partially uploaded!';
                break;
            case 4:
                $rtn = 'No file was uploaded!';
                break;
            case 6:
                $rtn = 'templrary folder not find!';
                break;
            case 7:
                $rtn = 'File write failed!';
                break;
        }
        return $rtn;
    }
}